

using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Swagger
{
    /// <summary>
    /// Swagger冲突操作解析器
    /// 用于解决多个控制器具有相同路由模式时的冲突问题
    /// </summary>
    public class SwaggerConflictingActionsResolver
    {
        /// <summary>
        /// 解析冲突的操作，选择一个最佳的操作描述符
        /// </summary>
        /// <param name="apiDescriptions">冲突的API描述符列表</param>
        /// <returns>选择的API描述符</returns>
        public ApiDescription? ResolveConflictingActions(IEnumerable<ApiDescription> apiDescriptions)
        {
            var descriptions = apiDescriptions.ToList();
            
            if (!descriptions.Any())
                return null;

            // 如果只有一个描述符，直接返回
            if (descriptions.Count == 1)
                return descriptions.First();

            // 对于多个冲突的操作，采用以下优先级策略：
            
            // 1. 优先选择有更完整参数的操作（从Body接收参数的优先级更高）
            var withBodyParams = descriptions
                .Where(d => d.ParameterDescriptions.Any(p => p.Source.Id == "Body"))
                .ToList();
                
            if (withBodyParams.Count == 1)
                return withBodyParams.First();

            // 2. 优先选择参数更多的操作
            var maxParamCount = descriptions.Max(d => d.ParameterDescriptions.Count);
            var withMaxParams = descriptions
                .Where(d => d.ParameterDescriptions.Count == maxParamCount)
                .ToList();
                
            if (withMaxParams.Count == 1)
                return withMaxParams.First();

            // 3. 根据控制器名称进行选择，优先选择更具体的控制器
            var controllerPriorities = new Dictionary<string, int>
            {
                { "PublishingController", 1 },  // 发布流程控制器
                { "ContentController", 2 },
                { "MediaController", 3 },
                { "CategoriesController", 4 }
            };

            var prioritizedDescriptions = descriptions
                .Select(d => new 
                { 
                    Description = d,
                    ControllerName = GetControllerName(d),
                    Priority = GetControllerPriority(d, controllerPriorities)
                })
                .OrderBy(x => x.Priority)
                .ThenBy(x => x.ControllerName)
                .ToList();

            var bestMatch = prioritizedDescriptions.FirstOrDefault();
            if (bestMatch != null)
            {
                return bestMatch.Description;
            }

            // 4. 如果以上策略都无法区分，选择第一个
            return descriptions.First();
        }

        /// <summary>
        /// 获取控制器名称
        /// </summary>
        /// <param name="apiDescription">API描述符</param>
        /// <returns>控制器名称</returns>
        private string GetControllerName(ApiDescription apiDescription)
        {
            if (apiDescription.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                return controllerActionDescriptor.ControllerName + "Controller";
            }
            
            return "UnknownController";
        }

        /// <summary>
        /// 获取控制器优先级
        /// </summary>
        /// <param name="apiDescription">API描述符</param>
        /// <param name="priorities">优先级映射表</param>
        /// <returns>优先级数值（越小优先级越高）</returns>
        private int GetControllerPriority(ApiDescription apiDescription, Dictionary<string, int> priorities)
        {
            var controllerName = GetControllerName(apiDescription);
            return priorities.TryGetValue(controllerName, out var priority) ? priority : int.MaxValue;
        }
    }
}
